/**
 * 图数据验证器
 * 用于验证和标准化图数据格式
 */

class GraphDataValidator {
  constructor() {
    // 支持的节点类型
    this.supportedNodeTypes = [
      'person', 'organization', 'location', 'event', 
      'concept', 'document', 'product', 'service', 'default'
    ]
    
    // 支持的边类型
    this.supportedEdgeTypes = [
      'belongs_to', 'works_for', 'located_in', 'related_to',
      'contains', 'depends_on', 'connects_to', 'similar_to',
      'manages', 'developed_by', 'uses', 'serves', 'uses_technology',
      'provides', 'collaborates_with', 'expert_in'
    ]
  }

  /**
   * 验证图数据格式
   * @param {Object} data - 图数据
   * @returns {Object} 验证结果
   */
  validate(data) {
    const errors = []
    const warnings = []

    // 检查顶层结构
    if (!data || typeof data !== 'object') {
      errors.push('数据必须是一个对象')
      return { isValid: false, errors, warnings, data: null }
    }

    // 检查必需字段
    if (!data.nodes) {
      errors.push('缺少必需的 nodes 字段')
    }
    if (!data.edges) {
      errors.push('缺少必需的 edges 字段')
    }

    if (errors.length > 0) {
      return { isValid: false, errors, warnings, data: null }
    }

    // 验证节点
    const nodeValidation = this.validateNodes(data.nodes)
    errors.push(...nodeValidation.errors)
    warnings.push(...nodeValidation.warnings)

    // 验证边
    const edgeValidation = this.validateEdges(data.edges, data.nodes)
    errors.push(...edgeValidation.errors)
    warnings.push(...edgeValidation.warnings)

    // 验证元数据
    if (data.metadata) {
      const metadataValidation = this.validateMetadata(data.metadata)
      warnings.push(...metadataValidation.warnings)
    } else {
      warnings.push('建议添加 metadata 字段以提供图谱信息')
    }

    return {
      isValid: errors.length === 0,
      errors,
      warnings,
      data: this.normalizeData(data)
    }
  }

  /**
   * 验证节点数据
   */
  validateNodes(nodes) {
    const errors = []
    const warnings = []

    if (!Array.isArray(nodes)) {
      errors.push('nodes 必须是数组格式')
      return { errors, warnings }
    }

    const nodeIds = new Set()

    nodes.forEach((node, index) => {
      // 检查必需字段
      if (!node.id) {
        errors.push(`节点 ${index} 缺少必需的 id 字段`)
      } else {
        // 检查ID唯一性
        if (nodeIds.has(node.id)) {
          errors.push(`节点ID "${node.id}" 重复`)
        }
        nodeIds.add(node.id)
      }

      if (!node.name) {
        errors.push(`节点 "${node.id || index}" 缺少必需的 name 字段`)
      }

      if (!node.type) {
        errors.push(`节点 "${node.id || index}" 缺少必需的 type 字段`)
      } else if (!this.supportedNodeTypes.includes(node.type)) {
        warnings.push(`节点 "${node.id}" 使用了不标准的类型 "${node.type}"`)
      }

      // 检查可选字段格式
      if (node.group !== undefined && (typeof node.group !== 'number' || node.group < 0)) {
        warnings.push(`节点 "${node.id}" 的 group 应该是非负数字`)
      }

      if (node.size !== undefined && (typeof node.size !== 'number' || node.size <= 0)) {
        warnings.push(`节点 "${node.id}" 的 size 应该是正数`)
      }

      if (node.position && typeof node.position === 'object') {
        const { x, y, z } = node.position
        if (x !== undefined && typeof x !== 'number') {
          warnings.push(`节点 "${node.id}" 的 position.x 应该是数字`)
        }
        if (y !== undefined && typeof y !== 'number') {
          warnings.push(`节点 "${node.id}" 的 position.y 应该是数字`)
        }
        if (z !== undefined && typeof z !== 'number') {
          warnings.push(`节点 "${node.id}" 的 position.z 应该是数字`)
        }
      }
    })

    return { errors, warnings }
  }

  /**
   * 验证边数据
   */
  validateEdges(edges, nodes) {
    const errors = []
    const warnings = []

    if (!Array.isArray(edges)) {
      errors.push('edges 必须是数组格式')
      return { errors, warnings }
    }

    // 创建节点ID集合用于验证
    const nodeIds = new Set()
    if (Array.isArray(nodes)) {
      nodes.forEach(node => {
        if (node.id) nodeIds.add(node.id)
      })
    }

    const edgeIds = new Set()

    edges.forEach((edge, index) => {
      // 检查必需字段
      if (!edge.source) {
        errors.push(`边 ${index} 缺少必需的 source 字段`)
      } else if (!nodeIds.has(edge.source)) {
        errors.push(`边 ${index} 的 source "${edge.source}" 不存在对应的节点`)
      }

      if (!edge.target) {
        errors.push(`边 ${index} 缺少必需的 target 字段`)
      } else if (!nodeIds.has(edge.target)) {
        errors.push(`边 ${index} 的 target "${edge.target}" 不存在对应的节点`)
      }

      if (!edge.type) {
        errors.push(`边 ${index} 缺少必需的 type 字段`)
      } else if (!this.supportedEdgeTypes.includes(edge.type)) {
        warnings.push(`边 ${index} 使用了不标准的类型 "${edge.type}"`)
      }

      // 检查ID唯一性（如果提供了ID）
      if (edge.id) {
        if (edgeIds.has(edge.id)) {
          errors.push(`边ID "${edge.id}" 重复`)
        }
        edgeIds.add(edge.id)
      }

      // 检查可选字段格式
      if (edge.weight !== undefined && (typeof edge.weight !== 'number' || edge.weight < 0)) {
        warnings.push(`边 ${index} 的 weight 应该是非负数字`)
      }

      if (edge.width !== undefined && (typeof edge.width !== 'number' || edge.width <= 0)) {
        warnings.push(`边 ${index} 的 width 应该是正数`)
      }

      if (edge.directed !== undefined && typeof edge.directed !== 'boolean') {
        warnings.push(`边 ${index} 的 directed 应该是布尔值`)
      }
    })

    return { errors, warnings }
  }

  /**
   * 验证元数据
   */
  validateMetadata(metadata) {
    const warnings = []

    if (!metadata.name) {
      warnings.push('建议在 metadata 中添加 name 字段')
    }

    if (!metadata.version) {
      warnings.push('建议在 metadata 中添加 version 字段')
    }

    if (!metadata.description) {
      warnings.push('建议在 metadata 中添加 description 字段')
    }

    return { warnings }
  }

  /**
   * 标准化数据格式
   */
  normalizeData(data) {
    const normalized = { ...data }

    // 标准化节点
    if (normalized.nodes) {
      normalized.nodes = normalized.nodes.map(node => ({
        id: node.id,
        name: node.name,
        type: node.type,
        label: node.label || node.name,
        category: node.category || node.type,
        group: node.group || 1,
        size: node.size || 10,
        color: node.color,
        position: node.position,
        properties: node.properties || {},
        ...node // 保留其他字段
      }))
    }

    // 标准化边
    if (normalized.edges) {
      normalized.edges = normalized.edges.map((edge, index) => ({
        id: edge.id || `edge_${index}`,
        source: edge.source,
        target: edge.target,
        type: edge.type,
        label: edge.label || edge.type,
        weight: edge.weight || 1.0,
        color: edge.color,
        width: edge.width || 1,
        directed: edge.directed !== false, // 默认有向
        properties: edge.properties || {},
        ...edge // 保留其他字段
      }))
    }

    // 添加默认元数据
    if (!normalized.metadata) {
      normalized.metadata = {
        name: 'Unnamed Graph',
        version: '1.0.0',
        description: 'Graph data',
        created_at: new Date().toISOString(),
        node_count: normalized.nodes ? normalized.nodes.length : 0,
        edge_count: normalized.edges ? normalized.edges.length : 0
      }
    } else {
      normalized.metadata.node_count = normalized.nodes ? normalized.nodes.length : 0
      normalized.metadata.edge_count = normalized.edges ? normalized.edges.length : 0
    }

    return normalized
  }

  /**
   * 从旧格式转换数据
   */
  convertLegacyFormat(data) {
    const converted = {
      metadata: {
        name: 'Converted Graph',
        version: '1.0.0',
        description: 'Converted from legacy format',
        created_at: new Date().toISOString()
      },
      nodes: [],
      edges: []
    }

    // 转换节点（支持对象格式转数组格式）
    if (data.nodes) {
      if (Array.isArray(data.nodes)) {
        converted.nodes = data.nodes
      } else if (typeof data.nodes === 'object') {
        // 对象格式转数组格式
        converted.nodes = Object.keys(data.nodes).map(id => ({
          id: id,
          name: data.nodes[id].name || id,
          type: data.nodes[id].type || 'default',
          ...data.nodes[id]
        }))
      }
    }

    // 转换边（支持 links 字段）
    const edgesData = data.edges || data.links || []
    if (Array.isArray(edgesData)) {
      converted.edges = edgesData.map((edge, index) => ({
        id: edge.id || `edge_${index}`,
        source: edge.source,
        target: edge.target,
        type: edge.type || 'related_to',
        ...edge
      }))
    }

    return converted
  }
}

export default GraphDataValidator



